#!/usr/bin/env python
# -*- coding: utf-8 -*-

import json
from flask import Flask, jsonify, request , redirect
import requests
import re
from flask_cors import *
# import paho.mqtt.client as mqtt
# from gevent import pywsgi

app = Flask(__name__, static_url_path='/')
CORS(app,supports_credentials=True)

URL = 'http://xyclstudy.cn:5002/WeBASE-Front/trans/handle'
BASE_URL = 'http://xyclstudy.cn:5002/WeBASE-Front'


# 智能合约相关信息
CONTRACT_NAME = 'Trace'

CONTRACT_ADDRESS = '0x4c034f72dd1de85d6196981809c794afd9ee0b3e'


CONTRACT_ABI  = '[{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"isProcessor","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"traceNumber","type":"uint256"}],"name":"getCornDeviceInfo","outputs":[{"name":"","type":"uint256[]"},{"name":"","type":"uint8[]"},{"name":"","type":"uint8[]"},{"name":"","type":"uint16[]"},{"name":"","type":"uint16[]"},{"name":"","type":"uint8[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"traceNumber","type":"uint256"}],"name":"getTraceInfo","outputs":[{"name":"","type":"uint256[]"},{"name":"","type":"uint8[]"},{"name":"","type":"string[]"},{"name":"","type":"address[]"},{"name":"","type":"uint8[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"cornKind","type":"string"},{"name":"tracePrice","type":"uint8"},{"name":"traceNumber","type":"uint256"},{"name":"traceName","type":"string"},{"name":"quality","type":"uint8"},{"name":"deviceTraceNumber","type":"uint256"}],"name":"newCorn","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"addProcessor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"isPlanter","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"addPlanter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceProcessor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"traceNumber","type":"uint256"}],"name":"getCorn","outputs":[{"name":"","type":"uint256"},{"name":"","type":"uint8"},{"name":"","type":"string"},{"name":"","type":"string"},{"name":"","type":"string"},{"name":"","type":"address"},{"name":"","type":"uint8"},{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"isRetailer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"isDevice","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"deviceName","type":"string"},{"name":"status","type":"uint8"},{"name":"deviceTraceNumber","type":"uint256"}],"name":"newDevice","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"addRetailer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"traceNumber","type":"uint256"},{"name":"traceName","type":"string"},{"name":"quality","type":"uint8"}],"name":"addTraceInfoByRetailer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"addDevice","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"traceNumber","type":"uint256"}],"name":"traceOver","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"traceNumber","type":"uint256"},{"name":"traceName","type":"string"},{"name":"quality","type":"uint8"}],"name":"addTraceInfoByProcessor","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceDevice","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"temp","type":"uint8"},{"name":"humi","type":"uint8"},{"name":"lux","type":"uint16"},{"name":"pa","type":"uint16"},{"name":"alt","type":"uint8"},{"name":"deviceTraceNumber","type":"uint256"},{"name":"status","type":"uint8"}],"name":"addDeviceinfo","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceRetailer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renouncePlanter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getAllCorn","outputs":[{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"planter","type":"address"},{"name":"processor","type":"address"},{"name":"retailer","type":"address"},{"name":"device","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"DeviceAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"DeviceRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"RetailerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"RetailerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"ProcessorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"ProcessorRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"PlanterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"PlanterRemoved","type":"event"}]'

DEVICE_ADDRESS = '0x74ef053dec4f8af89f49285ffc25a83a3e8beb5a'
PROCESSOR_ADDRESS = '0x0f0c7a47a631edb3bdfec7fec511ff6a5882242d'
PLANTER_ADDRESS = '0xc1caf4a2316355e488e81c10c0881377723cfefe'
RETAILER_ADDRESS = '0x8de431418a156b479891ef80c26589d3f997419e59'

USER_ADDRESS=''


#设置拦截器,当未获取user_address时需要获取
@app.before_request
def before():
    global USER_ADDRESS
    print(USER_ADDRESS)
    if USER_ADDRESS=='':
        private_key()
    else:
        pass

@app.route('/', methods=['GET'])
def index():
    # return redirect('/privateKey', code=301)
    return "teaTrace_API is runing"

@app.route('/privateKey',methods=['GET'])
def private_key():
    result=requests.get(BASE_URL+'/privateKey'+'?type=0&userName='+str('0xeebab5b78d8094a9829ca49e1190dda56a34a23c'))
    jsonObj=result.json()
    if(str(result.status_code)=='200'):
        global USER_ADDRESS
        USER_ADDRESS = jsonObj['address']
        print(USER_ADDRESS)
        return 'get useraddress successfully', 200
    return 'fail',500

# 添加硬件设备信息
@app.route('/newdevice', methods=["POST"])
def new_device():
    # 生产商生产食品
    body = request.get_data()
    if not body:
        return 'invalid parameter', 404

    deviceName = request.form["deviceName"]
    status = request.form["status"]
    deviceTraceNumber = request.form["deviceTraceNumber"]

    params = [deviceName, status,deviceTraceNumber]

    payload = json.dumps(
        {'contractName': CONTRACT_NAME, "contractAddress": CONTRACT_ADDRESS, "contractAbi": json.loads(CONTRACT_ABI),
         "user": DEVICE_ADDRESS, "funcName": "newDevice", "funcParam": params})
    headers = {'Content-Type': 'application/json'}
    result = requests.post(URL, headers=headers, data=payload)
    print(result.json())
    msg = json.loads(result.content.decode())["message"]
    # DeviceRole: caller does not have the device role
    if msg == "Success":
        return jsonify({'ret': 1, 'msg': msg})
    else:
        return jsonify({'ret': 0, 'msg': msg})

# 添加玉米生产信息
@app.route('/planter', methods=["POST"])
def planter():
    # 生产商生产食品
    body = request.get_data()
    if not body:
        return 'invalid parameter', 404
    # body = json.loads(body.decode())
    cornKind = request.form["cornKind"]
    trace_price = request.form["tracePrice"]
    trace_number = request.form["traceNumber"]
    trace_name = request.form["traceName"]
    quality = request.form["quality"]
    deviceTraceNumber = request.form["deviceTraceNumber"]

    params = [cornKind, trace_price, trace_number, trace_name, quality,deviceTraceNumber]

    payload = json.dumps(
        {'contractName': CONTRACT_NAME, "contractAddress": CONTRACT_ADDRESS, "contractAbi": json.loads(CONTRACT_ABI),
         "user": PLANTER_ADDRESS, "funcName": "newCorn", "funcParam": params})
    headers = {'Content-Type': 'application/json'}
    result = requests.post(URL, headers=headers, data=payload)
    print(result.content)
    msg = json.loads(result.content.decode())["message"]
    print(msg)
    if msg == "Success":
        return jsonify({'ret': 1, 'msg': msg})
    else:
        return jsonify({'ret': 0, 'msg': msg})

# 加工厂添加玉米流转信息
@app.route('/addprocessor', methods=["POST"])
def add_trace_by_distrubutor():
    body = request.get_data()
    if not body:
        return 'invalid parameter', 404
    # #body = json.loads(body.decode())

    trace_Number = request.form["traceNumber"]
    trace_Name = request.form["traceName"]
    quality = request.form["quality"]

    params = [trace_Number, trace_Name, quality]
    payload = json.dumps(
        {'contractName': CONTRACT_NAME, "contractAddress": CONTRACT_ADDRESS, "contractAbi": json.loads(CONTRACT_ABI),
         "user": PROCESSOR_ADDRESS, "funcName": "addTraceInfoByProcessor", "funcParam": params})

    headers = {'Content-Type': 'application/json'}
    result = requests.post(URL, headers=headers, data=payload)
    msg = json.loads(result.content.decode())["message"]
    if msg == "Success":
        return jsonify({'ret': 1, 'msg': msg})
    else:
        return jsonify({'ret': 0, 'msg': msg})

# 销售商添加食品流转信息
@app.route('/addretail', methods=["POST"])
def add_trace_by_retailer():
    body = request.get_data()
    if not body:
        return 'invalid parameter', 404
    #body = json.loads(body.decode())

    trace_Number = request.form["traceNumber"]
    trace_Name = request.form["traceName"]
    quality = request.form["quality"]

    params = [trace_Number, trace_Name, quality]
    payload = json.dumps(
        {'contractName': CONTRACT_NAME, "contractAddress": CONTRACT_ADDRESS, "contractAbi": json.loads(CONTRACT_ABI),
         "user": RETAILER_ADDRESS, "funcName": "addTraceInfoByRetailer", "funcParam": params})

    headers = {'Content-Type': 'application/json'}
    result = requests.post(URL, headers=headers, data=payload)
    print(result.content)
    msg = json.loads(result.content.decode())["message"]
    if msg == "Success":
        return jsonify({'ret': 1, 'msg': msg})
    else:
        return jsonify({'ret': 0, 'msg': msg})

# 添加设备传感器数据信息
@app.route('/adddeviceinfo', methods=["POST"])
def add_trace_by_device():
    body = request.get_data()
    if not body:
        return 'invalid parameter', 404
    #body = json.loads(body.decode())

    temp = request.form["temp"]
    humi = request.form["humi"]
    lux = request.form["lux"]
    pa = request.form["pa"]
    alt = request.form["alt"]
    deviceTraceNumber = request.form["deviceTraceNumber"]
    status = request.form["status"]

    params = [temp, humi, lux,pa,alt,deviceTraceNumber,status]

    payload = json.dumps(
        {'contractName': CONTRACT_NAME, "contractAddress": CONTRACT_ADDRESS, "contractAbi": json.loads(CONTRACT_ABI),
         "user": DEVICE_ADDRESS, "funcName": "addDeviceinfo", "funcParam": params})

    headers = {'Content-Type': 'application/json'}
    result = requests.post(URL, headers=headers, data=payload)
    msg = json.loads(result.content.decode())["message"]
    if msg == "Success":
        return jsonify({'ret': 1, 'msg': msg})
    else:
        return jsonify({'ret': 0, 'msg': msg})


# 获取所有玉米信息
# return: 所有玉米信息列表
@app.route('/cornlist', methods=["GET"])
def getlist():
    num_list = get_corn_list()
    num_list = json.loads(num_list[0])
    res = []
    for num in num_list:
        corn = get_corn(num)
        res.append(corn)
    return jsonify(res)

# 获取某个食品的溯源信息
@app.route('/trace', methods=["GET"])
def trace():
    trace_number = request.form["traceNumber"]
    if not trace_number:
        return 'invalid parameter', 404
    res = get_trace(trace_number)
    return jsonify(res)

# 获取某个食品的当前信息
# traceNumber: 食品溯源id，食品溯源过程中的标识符
# return: 对应食品的当前信息
@app.route('/corn', methods=["GET"])
def corn():
    trace_number = request.form["traceNumber"]
    if not trace_number:
        return 'invalid parameter', 404
    res = get_corn(trace_number)
    return jsonify(res)

# 获取所有食品的最新溯源信息
# return: 所有食品的最新溯源信息
@app.route('/newtracelist', methods=["GET"])
def get_latest():
    num_list = get_corn_list()
    num_list = json.loads(num_list[0])
    res = []
    for num in num_list:
        trace = get_trace(num)
        res.append(trace[-1])
    return jsonify(res)

# 获取位于生产商的的食物信息
# return: 所有位于生产商的食品信息列表
@app.route('/planting', methods=["GET"])
def get_planting():
    num_list = get_corn_list()
    num_list = json.loads(num_list[0])
    print(type(num_list))
    res = []
    for num in num_list:
        # print(num)
        trace = get_trace(num)
        if len(trace) == 1:
            res.append(trace[0])
    return jsonify(res)

# 获取位于中间商的食物信息
# return: 所有位于中间商的食品信息列表
@app.route('/progressing', methods=["GET"])
def get_progressing():
    num_list = get_corn_list()
    num_list = json.loads(num_list[0])
    res = []
    for num in num_list:
        trace = get_trace(num)
        if len(trace) == 2:
            res.append(trace[1])
    return jsonify(res)

# 获取位于超市的食物信息
# return: 所有位于超市的食品信息列表
@app.route('/retailing', methods=["GET"])
def get_retailing():
    num_list = get_corn_list()
    num_list = json.loads(num_list[0])
    res = []
    for num in num_list:
        trace = get_trace(num)
        if len(trace) == 3:
            res.append(trace[2])
    return jsonify(res)
# 玉米园被用户查询
@app.route('/traceover', methods=["GET"])
def trace_over(trace_number):
    params = [trace_number]
    payload = json.dumps(
        {"contractName": CONTRACT_NAME, "contractAddress": CONTRACT_ADDRESS, "contractAbi": json.loads(CONTRACT_ABI),
         "user": "", "funcName": "traceOver", "funcParam": params})
    headers = {'Content-Type': 'application/json'}
    result = requests.post(URL, headers=headers, data=payload)
    msg = json.loads(result.content.decode())
    if msg == "Success":
        return jsonify({'ret': 1, 'msg': msg})
    else:
        return jsonify({'ret': 0, 'msg': msg})

# 从链上获取所有食品信息
# return: 所有食品信息列表
def get_corn_list():
    payload = json.dumps(
        {"contractName": CONTRACT_NAME, "contractAddress": CONTRACT_ADDRESS, "contractAbi": json.loads(CONTRACT_ABI),
         "user": "", "funcName": "getAllCorn"})
    headers = {'Content-Type': 'application/json'}
    r = requests.post(URL, headers=headers, data=payload)
    #print(r.content.decode())
    return json.loads(r.content.decode())



# 从链上获取某个食品的基本信息
# traceNumber: 食品溯源id，食品溯源过程中的标识符
# return: 对应食品的信息


def get_corn(trace_number):
    params = [trace_number]
    payload = json.dumps(
        {"contractName": CONTRACT_NAME, "contractAddress": CONTRACT_ADDRESS, "contractAbi": json.loads(CONTRACT_ABI),
         "user": "", "funcName": "getCorn", "funcParam": params})
    headers = {'Content-Type': 'application/json'}
    result = requests.post(URL, headers=headers, data=payload)
    corn = json.loads(result.content.decode())
    print(corn)
    return {"traceNumber": trace_number, "timestamp": int(corn[0]), "price": corn[1], "name": corn[2], "kind": corn[3],"address":corn[5],"quality":corn[6],"status":corn[7]}

# 从链上获取某个食品的溯源信息
# traceNumber: 食品溯源id，食品溯源过程中的标识符
# return: 对应食品的溯源信息
def get_trace(traceNumber):
    # 获取食品基本信息
    params = [traceNumber]
    headers = {'Content-Type': 'application/json'}
    payload = json.dumps(
        {"contractName": CONTRACT_NAME, "contractAddress": CONTRACT_ADDRESS, "contractAbi": json.loads(CONTRACT_ABI),
         "user": "", "funcName": "getCorn", "funcParam": params})
    result = requests.post(URL, headers=headers, data=payload)
    corn = json.loads(result.content.decode())
    # [[[2-2]]]
    ### 获取食品溯源信息
    payload = json.dumps(
        {"contractName": CONTRACT_NAME, "contractAddress": CONTRACT_ADDRESS, "contractAbi": json.loads(CONTRACT_ABI),
         "user": "", "funcName": "getTraceInfo", "funcParam": params})
    result = requests.post(URL, headers=headers, data=payload)
    Res = result.content.decode()
    res = []
    if(Res=="[\"Call contract return error: traceNumber does not exist\"]"):
        print("error")
        return res
    else:
        # res= json.loads(result.content.decode())
        time_list, price_list, name_list, address_list, quality_list = json.loads(result.content.decode())
        # print(time_list, name_list, address_list, quality_list)
        # time_list = re.findall(r'\[ (.*?) \]', time_list)
        # name_list = re.findall(r'\[ "(.*?)" \]', name_list)
        # address_list = re.findall(r'\[ (.*?) \]', address_list)
        # quality_list = re.findall(r'\[ (.*?) \]', quality_list)
        time_list = json.loads(time_list)
        price_list = json.loads(price_list)
        name_list = json.loads(name_list)
        address_list = json.loads(address_list)
        quality_list = json.loads(quality_list)
        # print(time_list,name_list,address_list,quality_list)
        # res.append({"traceNumber": traceNumber, "name": corn[2], "produce_time": int(corn[0]), "timestamp": int(time_list[0]),"from": name_list[0], "quality": quality_list[0], "from_address":address_list[0]})
        for i in range(len(time_list)):
            if i == 0:
                res.append({"traceNumber": traceNumber, "name": corn[2], "produce_time": corn[0], "timestamp": time_list[i],
                            "from": name_list[i], "price":price_list[i],"quality": quality_list[i], "from_address":address_list[i],"kind": corn[3]})
            else:
                res.append({"traceNumber": traceNumber, "name": corn[2], "produce_time": corn[0], "timestamp": time_list[i],
                            "from": name_list[i - 1], "price":price_list[i],"to": name_list[i], "quality": quality_list[i], "from_address":address_list[i - 1], "to_address":address_list[i],"kind": corn[3]})
        return res

# 从链上获取所有传感器采集的数据
@app.route('/getdevicetrace', methods=["POST"])
def get_device_trace():
    body = request.get_data()
    #body = json.loads(body.decode())

    params=[request.form["traceNumber"]]
    headers = {'Content-Type': 'application/json'}
    payload = json.dumps(
        {"contractName": CONTRACT_NAME, "contractAddress": CONTRACT_ADDRESS, "contractAbi": json.loads(CONTRACT_ABI),
         "user": "", "funcName": "getCornDeviceInfo", "funcParam": params})
    result = requests.post(URL, headers=headers, data=payload)
    print(result)
    # Res = result.content.decode()
    res = []
    return res



if __name__ == '__main__':
    # app.run(host='127.0.0.1', port= 3008)

    # server = pywsgi.WSGIServer(('127.0.0.1', 3008), app)
    # server.serve_forever()
    app.run(host='127.0.0.1', port=3008)
